/**
 *******************************************************************************
 * @file  usb_host_hid_keyboardapp.c
 * @brief The application layer for USB Host HID Keyboard handling
 @verbatim
   Change Logs:
   Date             Author          Notes
   2021-03-29       Linsq           First version
 @endverbatim
 *******************************************************************************
 * Copyright (C) 2020, Huada Semiconductor Co., Ltd. All rights reserved.
 *
 * This software component is licensed by HDSC under BSD 3-Clause license
 * (the "License"); You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                    opensource.org/licenses/BSD-3-Clause
 *
 *******************************************************************************
 */

/*******************************************************************************
 * Include files
 ******************************************************************************/
#include "usb_host_hid_keyboardapp.h"

/*******************************************************************************
 * Local type definitions ('typedef')
 ******************************************************************************/

/*******************************************************************************
 * Local pre-processor symbols/macros ('#define')
 ******************************************************************************/

/*******************************************************************************
 * Local function prototypes ('static')
 ******************************************************************************/
void keyboard_init(void);
void keyboard_decode(uint8_t *pbuf);

/*******************************************************************************
 * Global variable definitions (declared in header file with 'extern')
 ******************************************************************************/
#ifdef USB_INTERNAL_DMA_ENABLED
 #if defined   (__CC_ARM) /*!< ARM Compiler */
  __align(4)
 #elif defined ( __ICCARM__ ) /*!< IAR Compiler */
  #pragma data_alignment=4
 #elif defined (__GNUC__) /*!< GNU Compiler */
 #pragma pack(4)
 #endif /* __CC_ARM */
#endif

HID_cb_TypeDef HID_KEYBRD_cb=
{
    keyboard_init,
    keyboard_decode
};

/*******************************************************************************
 * Local variable definitions ('static')
 ******************************************************************************/
static  const  uint8_t  HID_KEYBRD_Codes[] =
{
    0,      0,      0,      0,      31,     50,     48,     33,
    19,     34,     35,     36,     24,     37,     38,     39,     /* 0x00 - 0x0F */
    52,     51,     25,     26,     17,     20,     32,     21,
    23,     49,     18,     47,     22,     46,     2,      3,      /* 0x10 - 0x1F */
    4,      5,      6,      7,      8,      9,      10,     11,
    43,     110,    15,     16,     61,     12,     13,     27,     /* 0x20 - 0x2F */
    28,     29,     42,     40,     41,     1,      53,     54,
    55,     30,     112,    113,    114,    115,    116,    117,    /* 0x30 - 0x3F */
    118,    119,    120,    121,    122,    123,    124,    125,
    126,    75,     80,     85,     76,     81,     86,     89,     /* 0x40 - 0x4F */
    79,     84,     83,     90,     95,     100,    105,    106,
    108,    93,     98,     103,    92,     97,     102,    91,     /* 0x50 - 0x5F */
    96,     101,    99,     104,    45,     129,    0,      0,
    0,      0,      0,      0,      0,      0,      0,      0,      /* 0x60 - 0x6F */
    0,      0,      0,      0,      0,      0,      0,      0,
    0,      0,      0,      0,      0,      0,      0,      0,      /* 0x70 - 0x7F */
    0,      0,      0,      0,      0,      107,    0,      56,
    0,      0,      0,      0,      0,      0,      0,      0,      /* 0x80 - 0x8F */
    0,      0,      0,      0,      0,      0,      0,      0,
    0,      0,      0,      0,      0,      0,      0,      0,      /* 0x90 - 0x9F */
    0,      0,      0,      0,      0,      0,      0,      0,
    0,      0,      0,      0,      0,      0,      0,      0,      /* 0xA0 - 0xAF */
    0,      0,      0,      0,      0,      0,      0,      0,
    0,      0,      0,      0,      0,      0,      0,      0,      /* 0xB0 - 0xBF */
    0,      0,      0,      0,      0,      0,      0,      0,
    0,      0,      0,      0,      0,      0,      0,      0,      /* 0xC0 - 0xCF */
    0,      0,      0,      0,      0,      0,      0,      0,
    0,      0,      0,      0,      0,      0,      0,      0,      /* 0xD0 - 0xDF */
    58,     44,     60,     127,    64,     57,     62,     128     /* 0xE0 - 0xE7 */
};

#ifdef QWERTY_KEYBOARD
static  const  int8_t  HID_KEYBRD_Key[] =
{
    '\0',   '`' ,   '1' ,   '2' ,   '3' ,   '4' ,   '5' ,   '6' ,
    '7' ,   '8' ,   '9' ,   '0' ,   '-' ,   '=' ,   '\0',   '\r',
    '\t',   'q' ,   'w' ,   'e' ,   'r' ,   't' ,   'y' ,   'u' ,
    'i' ,   'o' ,   'p' ,   '[' ,   ']' ,   '\\',
    '\0',   'a' ,   's' ,   'd' ,   'f' ,   'g' ,   'h' ,   'j' ,
    'k' ,   'l' ,   ';' ,   '\'',   '\0',   '\n',
    '\0',   '\0',   'z' ,   'x' ,   'c' ,   'v' ,   'b' ,   'n' ,
    'm' ,   ',' ,   '.' ,   '/' ,   '\0',   '\0',
    '\0',   '\0',   '\0',   ' ' ,   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\r',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '7' ,   '4' ,   '1' ,
    '\0',   '/',    '8' ,   '5' ,   '2' ,
    '0' ,   '*',    '9' ,   '6' ,   '3' ,
    '.' ,   '-',    '+' ,   '\0',   '\n',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0'
};

static  const  int8_t  HID_KEYBRD_ShiftKey[] = {
    '\0',   '~' ,   '!' ,   '@' ,   '#' ,   '$' ,   '%' ,   '^' ,   '&' ,   '*' ,   '(' ,   ')' ,
    '_' ,   '+' ,   '\0',   '\0',   '\0',   'Q' ,   'W' ,   'E' ,   'R' ,   'T' ,   'Y' ,   'U' ,
    'I' ,   'O' ,   'P' ,   '{' ,   '}' ,   '|' ,   '\0',   'A' ,   'S' ,   'D' ,   'F' ,   'G' ,
    'H' ,   'J' ,   'K' ,   'L' ,   ':' ,   '"' ,   '\0',   '\n',   '\0',   '\0',   'Z' ,   'X' ,
    'C' ,   'V' ,   'B' ,   'N' ,   'M' ,   '<' ,   '>' ,   '?' ,   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0'
};

#else

static  const  int8_t  HID_KEYBRD_Key[] = {
    '\0',   '`' ,   '1' ,   '2' ,   '3' ,   '4' ,   '5' ,   '6' ,   '7' ,   '8' ,   '9' ,   '0',
    '-' ,   '=' ,   '\0',   '\r',   '\t',   'a' ,   'z' ,   'e' ,   'r' ,   't' ,   'y' ,   'u',
    'i' ,   'o' ,   'p' ,   '[' ,   ']' ,   '\\',   '\0',   'q' ,   's' ,   'd' ,   'f' ,   'g',
    'h' ,   'j' ,   'k' ,   'l' ,   'm' ,   '\0',   '\0',   '\n',   '\0',   '\0',   'w' ,   'x',
    'c' ,   'v' ,   'b' ,   'n' ,   ',' ,   ';' ,   ':' ,   '!' ,   '\0',   '\0',   '\0',   '\0',
    '\0',   ' ' ,   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\r',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '7' ,   '4' ,   '1' ,   '\0',   '/',
    '8' ,   '5' ,   '2' ,   '0' ,   '*' ,   '9' ,   '6' ,   '3' ,   '.' ,   '-' ,   '+' ,   '\0',
    '\n',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0'
};

static  const  int8_t  HID_KEYBRD_ShiftKey[] = {
    '\0',   '~' ,   '!' ,   '@' ,   '#' ,   '$' ,   '%' ,   '^' ,   '&' ,   '*' ,   '(' ,   ')' ,   '_' ,
    '+' ,   '\0',   '\0',   '\0',   'A' ,   'Z' ,   'E' ,   'R' ,   'T' ,   'Y' ,   'U' ,   'I' ,   'O' ,
    'P' ,   '{' ,   '}' ,   '*' ,   '\0',   'Q' ,   'S' ,   'D' ,   'F' ,   'G' ,   'H' ,   'J' ,   'K' ,
    'L' ,   'M' ,   '%' ,   '\0',   '\n',   '\0',   '\0',   'W' ,   'X' ,   'C' ,   'V' ,   'B' ,   'N' ,
    '?' ,   '.' ,   '/' ,   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',
    '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0',   '\0'
};
#endif

/**
 *******************************************************************************
 ** \brief  Initialize the keyboard function.
 ** \param  none
 ** \retval none
 ******************************************************************************/
void keyboard_init(void)
{
    user_keyboard_init();
}

/**
 *******************************************************************************
* \brief  The function is to decode the pressed keys when receives key value.
* \param  pbuf : buffer contain the HID IN report data.
* \retval none
 ******************************************************************************/
void keyboard_decode(uint8_t *pbuf)
{
    static  uint8_t   shift;
    static  uint8_t   keys[KBR_MAX_NBR_PRESSED];
    static  uint8_t   keys_new[KBR_MAX_NBR_PRESSED];
    static  uint8_t   keys_last[KBR_MAX_NBR_PRESSED];
    static  uint8_t   key_newest;
    static  uint8_t   nbr_keys;
    static  uint8_t   nbr_keys_new;
    static  uint8_t   nbr_keys_last;
    uint8_t   ix;
    uint8_t   jx;
    uint8_t   error;
    uint8_t   output;

    nbr_keys      = 0;
    nbr_keys_new  = 0;
    nbr_keys_last = 0;
    key_newest    = 0x00;


    /* Check if Shift key is pressed */
    if ((pbuf[0] == KBD_LEFT_SHIFT) || (pbuf[0] == KBD_RIGHT_SHIFT))
    {
        shift = TRUE;
    }
    else
    {
        shift = FALSE;
    }

    error = FALSE;

    /* Check for the value of pressed key */
    for (ix = 2; ix < 2 + KBR_MAX_NBR_PRESSED; ix++)
    {
        if ((pbuf[ix] == 0x01) || (pbuf[ix] == 0x02) || (pbuf[ix] == 0x03))
        {
            error = TRUE;
        }
    }
    if (error == TRUE)
    {
        return;
    }
    nbr_keys     = 0;
    nbr_keys_new = 0;
    for (ix = 2; ix < 2 + KBR_MAX_NBR_PRESSED; ix++)
    {
        if (pbuf[ix] != 0)
        {
            keys[nbr_keys] = pbuf[ix];
            nbr_keys++;
            for (jx = 0; jx < nbr_keys_last; jx++)
            {
                if (pbuf[ix] == keys_last[jx])
                {
                    break;
                }
            }
            if (jx == nbr_keys_last)
            {
                keys_new[nbr_keys_new] = pbuf[ix];
                nbr_keys_new++;
            }
        }
    }
    if (nbr_keys_new == 1)
    {
        key_newest = keys_new[0];

        if (shift == TRUE)
        {
            output = HID_KEYBRD_ShiftKey[HID_KEYBRD_Codes[key_newest]];
        }
        else
        {
            output = HID_KEYBRD_Key[HID_KEYBRD_Codes[key_newest]];
        }
        /* call user process handle */
        user_keyboard_dataprocess(output);
    }
    else
    {
        key_newest = 0x00;
    }
    nbr_keys_last  = nbr_keys;
    for (ix = 0; ix < KBR_MAX_NBR_PRESSED; ix++)
    {
        keys_last[ix] = keys[ix];
    }
}

/*******************************************************************************
 * EOF (not truncated)
 ******************************************************************************/
